#include <iostream>
#include <thread>
#include <future>
#include <memory>

/**
 * std三种异步方式：
 *  1.async：传入任务函数，在内部自动创建工作线程，外部无法管理线程
 *  2.promise：任务函数需要有promise参数，异步线程需手动管理
 *  3.packaged_task：封装任务函数，异步线程需手动管理
*/

/**
 * packaged_task任务包，对函数进行封装
 * 可以通过get_future()获取一个future对象，得到这个函数的异步执行结果
*/

int taskAdd(int op1, int op2)
{
    return op1 + op2;
}

int main()
{
    // std::packaged_task<int(int, int)> task(taskAdd);
    // std::future<int> fut = task.get_future();

    // task不是可调用对象，只能直接调用
    
    // task(11, 22); //直接调用
    // std::async(std::launch::async, task, 11, 22); //类型不匹配，task不是可调用对象
    // std::thread t(task, 11, 22); //类型不匹配，task不是可调用对象
    
    // 异步调用task方案：将task的指针传递到线程中，再解引用执行
    // 栈上对象存在生命周期问题，故在堆上创建task对象，智能指针管理其生命周期

    std::shared_ptr<std::packaged_task<int(int, int)>> ptask = std::make_shared<std::packaged_task<int(int, int)>>(taskAdd);
    std::future<int> fut = ptask->get_future();
    std::thread t([ptask]() {
        (*ptask)(11, 22);
    });
    int sum = fut.get();

    std::cout << sum << std::endl;
    
    t.join();
    return 0;
}